import { ArgumentMetadata, Injectable, Paramtype, ValidationPipe } from "@nestjs/common";
import { DTO_VALIDATION_OPTIONS } from "./utils";

import * as merge from 'deepmerge';


import { isObject, omit } from 'lodash';

@Injectable()
export class AppPipe extends ValidationPipe {
    async transform(value: any, metadata: ArgumentMetadata) {
        const { metatype, type } = metadata;
        // 获取要验证的dto类
        const dto = metatype as any;
        // 获取dto类的装饰器元数据中的自定义验证选项
        const options = Reflect.getMetadata(DTO_VALIDATION_OPTIONS, dto) || {};
        // 把当前已设置的选项解构到备份对象
        const originOptions = { ...this.validatorOptions };
        // 把当前已设置的class-transform选项解构到备份对象
        const originTransform = { ...this.transformOptions };
        //对自定义 class-transform 进行解构
        const { transformOptions, paramType, ...customOptions } = options

        //获取值的方式默认为body
        let requestType = paramType ?? "body"
        if (requestType !== type) {
            return value
        }

        console.log(1);
        
        if (transformOptions) {

            this.transformOptions = merge(this.transformOptions, transformOptions ?? {}, {
                arrayMerge: (_d, s, _o) => s
            })
        }

        this.validatorOptions = merge(this.validatorOptions, customOptions ?? {}, {
            arrayMerge: (_d, s, _o) => s
        })
        const toValidator = isObject(value) ? Object.fromEntries(Object.entries((value as Record<string, any>)).map(([key, v]) => {
            if (!isObject(v) || ('mimetype' in v)) {
                return [key, v]
            } else {
                return [key, omit(v, ['fields'])]

            }
        })) : value


        let result = await super.transform(toValidator, metadata)
        if (typeof result.transform === 'function') {
            result = await result.transform(result)
            const { transform, ...data } = result
            result = data
        }
        this.transformOptions = originTransform 
        this.validatorOptions = originOptions 
        return result
    }
}